require"znetevent"
require'socket'
require'zdc.logger'

local EV_READ = znetevent.EV_READ
local EV_WRITE = znetevent.EV_WRITE
local EV_TIMEOUT = znetevent.EV_TIMEOUT
local EV_SIGNAL = znetevent.EV_SIGNAL
local EV_MAP={[EV_READ]='r',[EV_WRITE]='w',[EV_TIMEOUT]='t',[EV_SIGNAL]='s'}
local EV_RMAP={r=EV_READ,w=EV_WRITE,t=EV_TIMEOUT,s=EV_SIGNAL}
local pairs,insert=pairs,table.insert
module(..., package.seeall)

local React = {}
local React_mt = {__metatable = {}, __index = React}


function new(params)
	params=params or {}
	local obj = setmetatable({readset={},writeset={},wdog={},logger=params.logger or zdc.logger.defaultlog}, React_mt)
	obj.st=os.time()
	obj.le_base = znetevent.new(params.event_base, params.event_version)
	obj.logger:info("LUAEVENT version: " .. znetevent.libevent_version() .. " method: "..obj.le_base:method())
	obj.EV_READ=EV_READ
	obj.EV_WRITE=EV_WRITE
	obj.EV_TIMEOUT=EV_TIMEOUT
	--obj.EdgeTriger=true
	return obj
end

function React.sendfd(fd,buf,i,j)
	return znetevent.sendfd(fd,buf,i,j)
end
function React.recvfd(fd,i)
	return znetevent.recvfd(fd,i)
end
--[[
function React.sendfd(fd,buf,i,j)
	return fd:send(buf,i,j)
end
function React.recvfd(fd,i)
	return fd:receive(i)
end
--]]

function React:bvpcallcb(exch,p1,cb,bv,what)
	local r,v1=xpcall(function()return cb(p1,bv,what)end,debug.traceback)
	if r then return end
	self.logger:error(v1)
	r,v1=pcall(exch,p1)
	if not r then
		self.logger:error(v1)
	end
	return -1
end
--[[
function React:NewBV(exch,p1,fd,rc,wc,ec)
	return luaevent.core.bufferevent.new(self.le_base,fd,
						function(bv) self:bvpcallcb(exch,p1,rc,bv)end,
						function(bv) self:bvpcallcb(exch,p1,wc,bv)end,
						function(bv,wt) self:bvpcallcb(exch,p1,ec,bv,wt)end)
end
--]]
function React:pcallcb(exch,p1,cb,event)
	local r,v1,v2=pcall(cb,p1,event)
	if r then return v1,v2 end
	self.logger:error(v1)
	r,v1=pcall(exch,p1)
	if not r then
		self.logger:error(v1)
	end
	return -1
end

function React:AddEventCB(exch,p1,fd,event,cb,tm)
	return self.le_base:addevent(fd,event,function (event) return self:pcallcb(exch,p1,cb,event) end,tm)
end

function React:CloseCB(cbe)
	if cbe then cbe:close() end
end

function React:Dispatch(timeout)
	--self.le_base:loopexit(timeout)
	self.le_base:loop()
end
